<?
class CBaseComponent
{
	private $COMPONENTS_DIRECTORY;
	private $COMPONENT_NAMESPACE;
	private $COMPONENT_NAME;
	private $TEMPLATE;
	private $TEMPLATE_DEFAULT;
	private $TEMPLATE_PAGE;
	private $TEMPLATE_PAGE_DEFAULT;
	private $LANGUAGE_ID;
	private $DO_CACHE;
	private $CACHE;
	private $CACHE_TIME;
	private $CACHE_KEYS;
	private $arParams;
	private $arResult;
	private $obCache;

	function __construct($sComponent = NULL, $sTemplate = NULL, $arParams = NULL)
	{		
		// Устанавливаем директорию для всех компонентов
		$this->COMPONENTS_DIRECTORY = 'components';
		
		// Устанавливаем название папки шаблона по-умолчанию
		$this->TEMPLATE_DEFAULT  = 'default';
		
		// Устанавливаем название файла шаблона по-умолчанию
		$this->TEMPLATE_PAGE_DEFAULT = 'template';
		
		// Определяем пространство имен компонента и название компонента
		list($this->COMPONENT_NAMESPACE, $this->COMPONENT_NAME) = explode(':', $sComponent);
		
		// Устанавливаем название шаблона
		$this->TEMPLATE = $sTemplate ? $sTemplate : $this->TEMPLATE_DEFAULT;
		
		// Устанавливаем язык шаблона
		$this->LANGUAGE_ID = LANGUAGE_ID;
		
		// Устанавливаем параметры компонента из его настроек
		$this->arParams = $arParams;
	
		// Обрабатываем настройки кеширования
		$arParams['CACHE_TIME'] = (int) $arParams['CACHE_TIME'];
		$arParams['CACHE_TYPE'] = trim($arParams['CACHE_TYPE']);		
		$this->CACHE_TIME = $arParams['CACHE_TIME'] ? $arParams['CACHE_TIME'] : 0;
		$this->CACHE = $arParams['CACHE_TYPE'] == 'Y' ? true : false; 
		
		// Создаем объект кеша
		$this->CACHE ? $this->obCache = new CCache($this->CACHE_TIME) : '';
	}
	
	public function IncludeComponent()
	{
		global $APPLICATION;
		
		$arParams  = &$this->arParams;
		$arResult  = &$this->arResult;
		
		$component = SYSTEM_DOCUMENT_ROOT.'/'.SYSTEM_DIRECTORY.'/'.$this->COMPONENTS_DIRECTORY.'/'.$this->COMPONENT_NAMESPACE.'/'.$this->COMPONENT_NAME.'/'.'component.php';
		$component_lang_file = SYSTEM_DOCUMENT_ROOT.'/'.SYSTEM_DIRECTORY.'/'.$this->COMPONENTS_DIRECTORY.'/'.$this->COMPONENT_NAMESPACE.'/'.$this->COMPONENT_NAME.'/'.'lang'.'/'.$this->LANGUAGE_ID.'/'.'component.php';

		if(file_exists($component))
		{
			if(file_exists($component_lang_file)) include $component_lang_file;
			
			if(AJAX && AJAX_ID == $arParams['AJAX_ID'])
			{
				$APPLICATION->RestartBuffer();
				$arParams['IS_AJAX'] = true;
				include $component;
				return die();
			}
			
			return include $component;
		}
		else
		{
			CMain::ShowStringError('CAN NOT FIND COMPONENT: '.$this->COMPONENT_NAMESPACE.':'.$this->COMPONENT_NAME);
		}
		return false;
	}
	
	public function IncludeTemplate($sTemplatePage = NULL)
	{
		global $APPLICATION, $MESS;
		
		$arParams  = &$this->arParams;
		$arResult  = &$this->arResult;
		
		$this->TEMPLATE_PAGE = $sTemplatePage ? $sTemplatePage : $this->TEMPLATE_PAGE_DEFAULT;
		
		$result_modifier = SYSTEM_DOCUMENT_ROOT.'/'.SYSTEM_DIRECTORY.'/'.$this->COMPONENTS_DIRECTORY.'/'.$this->COMPONENT_NAMESPACE.'/'.$this->COMPONENT_NAME.'/'.'templates'.'/'.$this->TEMPLATE.'/'.'result_modifier.php';
		$result_modifier_lang_file = SYSTEM_DOCUMENT_ROOT.'/'.SYSTEM_DIRECTORY.'/'.$this->COMPONENTS_DIRECTORY.'/'.$this->COMPONENT_NAMESPACE.'/'.$this->COMPONENT_NAME.'/'.'templates'.'/'.$this->TEMPLATE.'/'.'lang'.'/'.$this->LANGUAGE_ID.'/'.'result_modifier.php';
		$template = SYSTEM_DOCUMENT_ROOT.'/'.SYSTEM_DIRECTORY.'/'.$this->COMPONENTS_DIRECTORY.'/'.$this->COMPONENT_NAMESPACE.'/'.$this->COMPONENT_NAME.'/'.'templates'.'/'.$this->TEMPLATE.'/'.$this->TEMPLATE_PAGE.'.php';
		$template_lang_file = SYSTEM_DOCUMENT_ROOT.'/'.SYSTEM_DIRECTORY.'/'.$this->COMPONENTS_DIRECTORY.'/'.$this->COMPONENT_NAMESPACE.'/'.$this->COMPONENT_NAME.'/'.'templates'.'/'.$this->TEMPLATE.'/'.'lang'.'/'.$this->LANGUAGE_ID.'/'.$this->TEMPLATE_PAGE.'.php';
		
		$styles_file = '/'.SYSTEM_DIRECTORY.'/'.$this->COMPONENTS_DIRECTORY.'/'.$this->COMPONENT_NAMESPACE.'/'.$this->COMPONENT_NAME.'/'.'templates'.'/'.$this->TEMPLATE.'/'.'styles.css';
		$javascript_file = '/'.SYSTEM_DIRECTORY.'/'.$this->COMPONENTS_DIRECTORY.'/'.$this->COMPONENT_NAMESPACE.'/'.$this->COMPONENT_NAME.'/'.'templates'.'/'.$this->TEMPLATE.'/'.'script.js';

		// Подключаем языковой файл для дополнительного обработчика
		if(file_exists($result_modifier_lang_file)) include $result_modifier_lang_file;
		
		// Подключаем дополнительный обработчик
		if(file_exists($result_modifier)) include $result_modifier;
		
		// Добавляем в <HEAD> css файл шаблона
		$APPLICATION->AddToHead(array('SRC'=>$styles_file, 'TYPE'=>'CSS'));
		
		// Добавляем в <HEAD> javascript файл шаблона
		$APPLICATION->AddToHead(array('SRC'=>$javascript_file, 'TYPE'=>'JS'));

		// Обрабатываем шаблон
		if(file_exists($template))
		{
			if(file_exists($template_lang_file)) include($template_lang_file);
			
			// Начинаем буферризацию вывода шаблона
			ob_start();		
			
			// Подключаем шаблон
			include($template);
			
			// Получаем данные из буффера
			$content = ob_get_contents();
			
			// Очищаем буффер
			ob_end_clean();
			
			// Выводим данные из буффера
			echo $content;
			
			// Кешируем данные из буффера
			if($this->CACHE && $this->DO_CACHE)
			{
				$this->SaveCache(array(
					'CONTENT'=>$content,
					'RESULT'=>$this->CACHE_KEYS,
					'FILES'=>array(
						array('SRC'=>$styles_file, 'TYPE'=>'CSS'),
						array('SRC'=>$javascript_file, 'TYPE'=>'JS')
					)
				));	
			}
			
			return true;
		}
		else
		{
			CMain::ShowStringError('CAN NOT FIND TEMPLATE: '.$this->TEMPLATE.' IN COMPONENT '.$this->COMPONENT_NAMESPACE.':'.$this->COMPONENT_NAME);
		}
		return false;
	}
	
	
	/**
	 * Метод выводит закешированные данные
	 * если включено кеширование и присутствует кеш
	 *
	 * @param int $iCacheTime
	 * @param array $arCacheId
	 * @return boolen
	 */
	public function InitCache($iCacheTime = NULL, $arCacheId = NULL)
	{
		global $APPLICATION;
		
		$arResult  = &$this->arResult;
		
		if($this->CACHE)
		{
			// Устанавливаем флаг кеширования
			$this->DO_CACHE = true;
			
			// Устанавливаем время актуальности кеша
			$iCacheTime ? $this->obCache->SetCacheTime($iCacheTime) : '';
			
			// Устанавливаем идентификатор кеша
			$this->obCache->SetCacheId($this->GetComponentCacheId($arCacheId));
			
			// Устанавливаем относительный путь до файла с кешем
			$this->obCache->SetCachePath($this->GetComponentCachePath());
			
			// Проверяем наличие кеша
			if($content = $this->obCache->Load())
			{
				// Выводим данные из кеша
				echo $content['CONTENT'];
				
				// Инициализируем переменные из кеша
				$arResult = $content['RESULT'];
				
				// Подключаем файлы css и js и добавляем их в <HEAD>.
				if(is_array($content['FILES']) && count($content['FILES']))
				{
					foreach ($content['FILES'] as $arFile)
					{
						$APPLICATION->AddToHead($arFile);
					}
				}
				return true;
			}
		}
		return false;
	}
	
	
	/**
	 * Метод сохраняет кеш данные
	 *
	 * @param string $sContent
	 */
	private function SaveCache($sContent = NULL)
	{
		$this->obCache->Save($sContent);
	}
	
	
	/**
	 * Метод формирует идентификатор компонента
	 *
	 * @param array $arCacheId
	 * @return string
	 */
	private function GetComponentCacheId($arCacheId = NULL)
	{
		$id = $this->COMPONENT_NAME.'|'.$this->TEMPLATE.'|';

		if(is_array($this->arParams) && count($this->arParams))
		{
			foreach($this->arParams as $k=>$v)
			{
				$id .= '|'.$k.'|'.serialize($v);
			}
		}

		if(is_array($arCacheId))
		{
			$id .= '|'.serialize($arCacheId);
		}

		return $id;
	}
	
	/**
	 * Метод возвращает идентификационный путь компонента для кеширования
	 *
	 * @return string
	 */
	private function GetComponentCachePath()
	{
		return $this->COMPONENT_NAMESPACE.'/'.$this->COMPONENT_NAME.'/'.$this->TEMPLATE;
	}
	
	/**
	 * Метод устанавливает данные которые необходимо закешировать вместе с контентом
	 *
	 * @param array $arCode
	 */
	public function SetCacheKeys($arCode = NULL)
	{
		if(is_array($arCode) && count($arCode) && is_array($this->arResult) && count($this->arResult))
		{
			foreach ($arCode as $code)
			{
				foreach ($this->arResult as $key=>$value)
				{
					if($key == $code)
					{
						$this->CACHE_KEYS[$key] = $value;
					}
				}
			}
			return true;
		}
		return false;
	}
}